/*
 * @Author: wuqingchun
 * @Date: 2024-10-29 19:37:24
 * @Description: 
 * @LastEditors: wuqingchun
 * @LastEditTime: 2024-11-01 09:13:39
 */

#include <cstdio>
#include <cstring>
#include <cerrno>

#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>

#include "libnet_error.h"
#include "net_connection_listener.h"
#include "net_connection_helper.h"



CNetConnectionListener::CNetConnectionListener(INetEventHandler& refEventHandler, INetTCPConnectionCallback& refCallback, const sockaddr_in& refAddr):
    m_refEventHandler(refEventHandler),
    m_refCallback(refCallback),
    m_stAddr(refAddr)
{
    
}

CNetConnectionListener::~CNetConnectionListener()
{
    Exit();
}

int32_t CNetConnectionListener::Init()
{
    int iSockFd = socket(AF_INET, SOCK_STREAM|SOCK_NONBLOCK, IPPROTO_TCP);
    if (iSockFd == -1)
    {
        printf("socket error, %s\n", strerror(errno));
        return ERROR_FAILED;
    }

    int iErr = bind(iSockFd, (const struct sockaddr*)&m_stAddr, sizeof(m_stAddr));
    if (iErr == -1)
    {
        close(iSockFd);
        return ERROR_FAILED;
    }

    iErr = listen(iSockFd, 1024);
    if (iErr == -1)
    {
        close(iSockFd);
        return ERROR_FAILED;
    }

    m_iSockFd = iSockFd;
    return m_refEventHandler.AddRDEvent(this);
}

void CNetConnectionListener::Exit()
{
    if (m_iSockFd != -1)
    {
        m_refEventHandler.DeleteRDEvent(this);
        close(m_iSockFd);
        m_iSockFd = -1;
    }

    for (auto& conn : m_setPassiveConn)
    {
        ((CNetConnectionPassive*)conn)->Close();
    }
}

void CNetConnectionListener::DeleteConnection(INetTCPConnection* pobjConnection)
{
    if (pobjConnection == nullptr)
    {
        return;
    }
    
    if (m_setPassiveConn.find(pobjConnection) == m_setPassiveConn.end())
    {
        return;
    }

    printf("Delete connection, %p\n", pobjConnection);
    m_setPassiveConn.erase(pobjConnection);
    delete pobjConnection;
}


int CNetConnectionListener::GetFd()
{
    return m_iSockFd;
}

int32_t CNetConnectionListener::DealRDEvent()
{
    CNetConnectionPassive* pobjConn = CNetConnectionHelper::CreatePassive(&m_refEventHandler, &m_refCallback, &m_stAddr, m_iSockFd);
    if (pobjConn != nullptr)
    {
        m_setPassiveConn.insert(pobjConn);
        printf("Accept new client connection\n");
    }

    return ERROR_SUCCESS;
}

int32_t CNetConnectionListener::DealWREvent()
{
    return ERROR_SUCCESS;
}

int32_t CNetConnectionListener::DealERREvent()
{
    return ERROR_SUCCESS;
}

int32_t CNetConnectionListener::Send(const void* pData, size_t ulDataLen)
{
    return ERROR_SUCCESS;
}


void CNetConnectionListener::Close()
{
    if (m_iSockFd != -1)
    {
        m_refEventHandler.DeleteRDEvent(this);
        close(m_iSockFd);
        m_iSockFd = -1;
    }

    for (auto& conn : m_setPassiveConn)
    {
        ((CNetConnectionPassive*)conn)->Close();
    }
}